package com.hczt.xhminiapp.adminapi.modules.login.controller;

import com.hczt.xhminiapp.adminapi.modules.login.service.UserLoginService;
import com.hczt.xhminiapp.adminapi.modules.login.vo.OAuth2Token;
import com.hczt.xhminiapp.adminapi.modules.system.service.SysUserService;
import com.hczt.xhminiapp.common.bean.CodeMsg;
import com.hczt.xhminiapp.common.bean.RtnResult;
import com.hczt.xhminiapp.common.utils.JacksonUtil;
import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.net.URI;
import java.util.Map;

/**
 * @author 红创-马海强
 * @date 2019-03-14 14:32
 * @description
 */
@Slf4j
@RequestMapping("/oauth2")
@RestController
public class UserLoginController {

    @Autowired
    private UserLoginService userLoginService;

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private RestTemplate restTemplate;

    @Value("${server.port}")
    private Integer port;

    @Value("${server.servlet.context-path}")
    private String contextPath;

    /**
     * Spring OAuth2 请求代理
     * 统一封装返回结果
     *
     * @param headers
     * @param params
     * @param request
     * @return
     * @throws IOException
     */
    @PostMapping(value = "/token")
    public Object token(@RequestHeader HttpHeaders headers, @RequestParam MultiValueMap<String, Object> params, HttpServletRequest request) throws IOException {
        log.info("URL:{}; Header:{}; Params:{}; ", request.getRequestURL().toString(), headers.toString(), params.toString());
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        //String url = request.getRequestURL().toString().replace("/oauth2/token", "/oauth/token");
        String url = this.getUrl(request);
        URI uri = restTemplate.getUriTemplateHandler().expand(url);
        RequestEntity requestEntity = new RequestEntity<>(params, headers, HttpMethod.POST, uri);
        try {
            ResponseEntity<OAuth2Token> responseEntity = restTemplate.exchange(requestEntity, OAuth2Token.class);
            return RtnResult.success(responseEntity.getBody());
        } catch (HttpClientErrorException e) {
            CodeMsg codeMsg = this.getCodeMsg(e, params);
            return new ResponseEntity<>(RtnResult.error(codeMsg), e.getStatusCode());
        }
    }

    private String getUrl(HttpServletRequest request){
        return String.format("http://127.0.0.1:%s%s/oauth/token", port, contextPath);
    }

    private CodeMsg getCodeMsg(HttpClientErrorException e, MultiValueMap<String, Object> params) throws IOException {
        Map<String, Object> body = JacksonUtil.json2Map(e.getResponseBodyAsString());
        String error = body.get("error").toString();
        switch (error) {
            case OAuth2Exception.INVALID_TOKEN:
                return CodeMsg.OAUTH2_INVALID_TOKEN;
            case OAuth2Exception.INVALID_CLIENT:
                return CodeMsg.OAUTH2_INVALID_CLIENT;
            case OAuth2Exception.INVALID_GRANT:
                return CodeMsg.OAUTH2_INVALID_GRANT;
            case OAuth2Exception.UNSUPPORTED_GRANT_TYPE:
                return CodeMsg.OAUTH2_UNSUPPORTED_GRANT_TYPE.fillArgs(params.get("grant_type"));
            default:
                return CodeMsg.OAUTH2_UNKNOWN_ERROR.fillArgs(error);
        }
    }
}
